{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "**Вопросы для повторения**:\n",
    "\n",
    "* что такое SFINAE и зачем эта техника нужна?\n",
    "* где здесь будет SFINAE error, а где hard error?\n",
    "\n",
    "```c++\n",
    "template<HERE>\n",
    "HERE my_function(HERE x, HERE y)\n",
    "{\n",
    "    HERE\n",
    "}\n",
    "```\n",
    "\n",
    "* Предположим, мы реализовали:\n",
    "\n",
    "```c++\n",
    "template<typename T>\n",
    "class has_swap_method {\n",
    "    constexpr static bool value = ...;  // имеет ли тип Т метод swap\n",
    "};\n",
    "```\n",
    "\n",
    "скомпилируется ли такой код?\n",
    "\n",
    "```c++\n",
    "template<typename T>\n",
    "void my_swap(T& x, T& y)\n",
    "{\n",
    "    if (has_swap_method<T>::value)\n",
    "    {\n",
    "        x.swap(y);\n",
    "    }\n",
    "    else\n",
    "    {\n",
    "        T t = std::move(x);\n",
    "        x = std::move(y);\n",
    "        y = std::move(t);\n",
    "    }\n",
    "}\n",
    "```\n",
    "\n",
    "как его исправить, чтобы он скомпилировался (3 варианта)\n",
    "\n",
    "<details>\n",
    "<summary>ответ</summary>\n",
    "<p>\n",
    "    \n",
    "1. if constexpr\n",
    "2. tag dispatching\n",
    "3. sfinae\n",
    "</p>\n",
    "</details>\n",
    "\n",
    "\n",
    "* как работает эта конструкция?\n",
    "\n",
    "```c++\n",
    "template<typename T>\n",
    "typename std::enable_if<has_swap_method<T>::value, void>::type\n",
    "my_swap(T& x, T& y)\n",
    "{\n",
    "    x.swap(y);\n",
    "}\n",
    "\n",
    "template<typename T>\n",
    "typename std::enable_if<!has_swap_method<T>::value, void>::type\n",
    "my_swap(T& x, T& y)\n",
    "{\n",
    "    T t = std::move(x);\n",
    "    x = std::move(y);\n",
    "    y = std::move(t);\n",
    "}\n",
    "```\n",
    "\n",
    "* что такое variadic templates?\n",
    "* в чём здесь проблема? как починить?\n",
    "\n",
    "```c++\n",
    "template<typename ...Args>\n",
    "auto f(const Args&... args) {\n",
    "    return (...+args);\n",
    "}\n",
    "\n",
    "const auto x = f(\"hello\", \" \", \"c++\", \"!\");\n",
    "```\n",
    "\n",
    "* в чём здесь проблема? как починить?\n",
    "\n",
    "```c++\n",
    "int main()\n",
    "{\n",
    "    int x = 0;\n",
    "    bool x_ready = false;\n",
    "        \n",
    "    std::thread t([&](){\n",
    "        if (x_ready)\n",
    "            assert(x == 1);\n",
    "    });\n",
    "    \n",
    "    x = 1;\n",
    "    x_ready = true;\n",
    "}\n",
    "```\n",
    "\n",
    "<details>\n",
    "<summary>ответ</summary>\n",
    "<p>\n",
    "    \n",
    "1. не `join`-ится поток (`std::terminate`)\n",
    "2. `assert` некорректен, т.к. нет гарантий на порядок чтения-записи из памяти. Нужна acquire-release семантика у `std::atomic`, либо использовать `mutex`.\n",
    "\n",
    "</p>\n",
    "</details>\n"
   ]
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.6.9"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
